package com.polaris.live.ui.live.fragment.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.annotation.CallSuper
import androidx.viewbinding.ViewBinding
import androidx.viewpager.widget.VerticalViewPager
import androidx.viewpager.widget.ViewPager.SimpleOnPageChangeListener
import com.polaris.live.common.constant.PagConst.LIVE_LOADING_PAG
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.databinding.LiveLoadingBinding
import com.polaris.live.ui.live.bean.DragBean
import com.polaris.live.ui.live.widget.base.PagerDragView
import kotlin.math.max

/**
 * DragFragment
 *
 * @author Created by lucas on 2023/11/8 09:37
 */
abstract class DragFragment<VM : BaseViewModel, VB : ViewBinding, D : DragBean> : GestureFragment<VM, VB>() {

    private lateinit var mPdDrag: PagerDragView
    private lateinit var mChildView: View
    private lateinit var mPdBinding: LiveLoadingBinding

    private val mAdapter: DragAdapter<D> by lazy {
        DragAdapter(requireContext())
    }

    private var mPosition = 0
    private var mScrollState: Int = VerticalViewPager.SCROLL_STATE_IDLE
    private var mErrorPosition = NORMAL

    private var mIsScroll = true

    @CallSuper
    override fun initView(savedInstanceState: Bundle?) {
        super.initView(savedInstanceState)

        val view = view

        check(view is PagerDragView) { "The layout of DragFragment must be <PagerDragView>." }

        mPdDrag = view
        check(mPdDrag.childCount == 1) { "DragDialog should have exactly one child View." }

        mChildView = mPdDrag.getChildAt(0)

        mPdBinding = LiveLoadingBinding.inflate(LayoutInflater.from(context), null, false)

        mPdDrag.addView(mPdBinding.root, 0)
        mPdDrag.setPager(mPdBinding.pager)

        mPdBinding.pager.adapter = mAdapter

        mPdDrag.setOnPageChangeListener(object : SimpleOnPageChangeListener() {
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int,
            ) {
                if (mPosition == position) {
                    scrollView(-positionOffsetPixels)
                } else {
                    scrollView(mPdBinding.pager.height - positionOffsetPixels)
                }
            }

            override fun onPageScrollStateChanged(state: Int) {
                mScrollState = state
                if (state == VerticalViewPager.SCROLL_STATE_IDLE && mAdapter.count > 1) {
                    switchView()
                }
            }
        })
        mPdDrag.setOnAllowScrollListener {
            this.isScroll()
        }

        mPdBinding.pagView.apply {
            path = LIVE_LOADING_PAG
            setRepeatCount(-1)
        }
    }

    /**
     * 是否允许滚动
     */
    @CallSuper
    open fun isScroll(): Boolean {
        return mIsScroll
    }

    private fun scrollView(offset: Int) {
        mChildView.translationY = offset.toFloat()
        if (mPdBinding.llLoading.visibility == View.VISIBLE) {
            mPdBinding.llLoading.translationY = offset.toFloat()
        }
        onScrollView(offset)
    }

    /**
     * 移动view
     *
     * @param offset 偏移量
     */
    protected abstract fun onScrollView(offset: Int)

    /**
     * 添加切换数据
     *
     * @param bean 数据
     * @param position 如果只是添加数据不需要设置
     */
    fun addSwitchData(bean: D, position: Int? = null) {
        mAdapter.add(bean)

        if (position != null) {
            mAdapter.hideView(position)

            mPdBinding.pager.currentItem = position
        }

        mAdapter.notifyDataSetChanged()
    }

    /**
     * 删除底部的数据
     */
    fun removeFooterData(test: (D) -> Boolean) {
        for (i in (mPosition until mAdapter.count)) {
            val item = mAdapter[i]
            if (test(item)) {
                mAdapter.remove(i)
                mAdapter.notifyDataSetChanged()
                break
            }
        }
    }

    fun setCurrentCover(anchorId: Long, block: (D?) -> D) {
        val bean = if (mPosition < mAdapter.count) {
            mAdapter[mPosition]
        } else {
            null
        }

        if (bean == null || bean.anchorId == anchorId) {
            setCurrentPageItem(block(bean))
        }
    }

    open fun setCurrentPageItem(bean: D) {
        mAdapter.set(bean, mPosition)
        mAdapter.notifyDataSetChanged()
    }

    private fun switchView() {
        val oldPosition = mPosition
        var newPosition: Int = mPdBinding.pager.currentItem

        if (oldPosition == newPosition) {
            return
        }
        if (mAdapter.count <= max(oldPosition, newPosition)) {
            return
        }

        val newDrag = mAdapter[newPosition]

        if (oldPosition == mErrorPosition) {
            mAdapter.remove(mErrorPosition)
            mAdapter.notifyDataSetChanged()

            if (newPosition > mErrorPosition) {
                mPdBinding.pager.currentItem = --newPosition
            }
        }

        mPosition = newPosition

        startLoading()

        scrollView(0)

        onSwitchView(newDrag)
    }

    /**
     * 开始切换
     *
     * @param bean 要切换的数据
     */
    abstract fun onSwitchView(bean: D)

    /**
     * 开始加载
     */
    protected open fun startLoading() {
        if (isLoading()) {
            return
        }

        mPdBinding.tvText.text = ""

        mPdDrag.setAllowScroll(false)
        mAdapter.showView()

        mPdBinding.llLoading.visibility = View.VISIBLE
        mPdBinding.pagView.visibility = View.VISIBLE
        mPdBinding.pagView.play()
    }

    /**
     * 加载成功
     */
    open fun loadSuccess(playSuccessful: Boolean = true) {
        if (!isLoading()) {
            return
        }

        mErrorPosition = -1

        if (playSuccessful) {
            playSuccessful()
        } else {
            mAdapter.notifyDataSetChanged()
        }

        mPdBinding.pagView.pause()
        mPdBinding.llLoading.visibility = View.GONE

        mPdDrag.setAllowScroll(true)
    }

    open fun playSuccessful() {
        mAdapter.hideView(mPosition)
    }

    /**
     * 加载失败
     *
     * @param message 错误信息
     */
    open fun loadFailure(message: String) {
        loadFailure(message, true)
    }

    open fun loadFailure(message: String, isScroll: Boolean) {
        if (!isLoading()) {
            return
        }
        mIsScroll = isScroll

        mErrorPosition = mPosition

        mPdBinding.tvText.text = message

        mPdBinding.pagView.pause()
        mPdBinding.pagView.visibility = View.GONE

        mPdDrag.setAllowScroll(true)
    }

    /**
     * 滑动到下一个
     */
    open fun scrollNext() {
        if (mAdapter.count > mPosition + 1) {
            mPdDrag.autoScrollToNextPage()
        }
    }

    /**
     * 获取当前所有的数据数量
     */
    fun getLoadCount(): Int {
        return mAdapter.count
    }

    /**
     * 是否加载中
     */
    fun isLoading(): Boolean {
        return (mPdBinding.llLoading.visibility == View.VISIBLE
                && mPdBinding.pagView.visibility == View.VISIBLE)
    }

    /**
     * 是否加载出错
     */
    fun isLoadError(): Boolean {
        return mPdBinding.llLoading.visibility == View.VISIBLE
                && mPdBinding.pagView.visibility == View.GONE
                && mPdBinding.tvText.visibility == View.VISIBLE
    }

    override fun isGesture(): Boolean {
        return !mPdDrag.isDisallowInterceptTouchEvent() && mScrollState == VerticalViewPager.SCROLL_STATE_IDLE
    }

    companion object {

        private const val NORMAL = -1

    }
}